环境
nc6.5
漏洞分析
接口/lfw/core/rpc
,对应hotwebs/lfw/WEB-INF/web.xml
中的LfwDispatcherServlet
,nc.uap.lfw.core.servlet.LfwDispatcherServlet
在pubwebrt_mvcLevel-1.jar
包中。
实例化了LfwCoreController
类,并调用了handleRequest
方法
调用了PresentPluginFactory.getControlPlugin(path)
方法
调用req.getPathInfo()
获取到的值为rpc
,创建new RpcControlPlugin()
对象
在RpcControlPlugin#handle
方法中,调用了RpcHelper.processJsonRequest(req, res)
方法
从request
中获取rpcdata
参数,并创建json对象,以json对象作为参数调用call(jsonReq)
方法
在call
方法中,首先从json中获取rpcname
和method
参数作为类名和方法名,再循环获取params
,添加到paramList
中。
获取完成后,会遍历paramList
,拿到参数值,调用LfwJsonSerializer.getInstance().fromJsObject(value)
方法。
1 | for(int i = 0; i < paramCount; ++i) { |
调用this.fromJSON(s)
方法
调用tok.nextValue()
在nextValue
方法中,首先会调用this.nextClean()
方法
在this.nextClean()
中,解析value
中注释区域,并将指向value
的指针指向注释区域后。
然后会判断当前所指向的value
是否为"
或者 '
,如果不是的话会跳过解析,直接调用this.nextString(c);
,如果是的话会继续判断是{
,会将value
解析成JSONObject
,是[
会将value
解析成JSONArray
对象。
只有是"
或者'
的情况下会调用this.nextString(c)
,参数c
就是"
或者'
,如果value
被"
或者'
包裹起来,那么就会返回被包裹的字符串。
后续还会判断是否以$S_
开头,如果以$S_
开头会截取$S_
后的内容,接着会对value
进行一次url解码。
接着会以className
作为参数调用ServiceLocator.getService(className)
调用ServiceLocator.getService(className)
这种方式为服务定位器模式
,这种设计模式在使用JNDI
加载类时,第一次加载后会对类进行缓存,第二次加载会从缓存中去加载,从而提高性能。
指定的className
为类路径,那么会在nameIndices
中进行查找,最后得到一个实例化对象。
最后并对其进行反射加载。
反射调用利用类
nc.uap.portal.service.itf.IPortalSpecService#createSkinFile
可实现任意路径下写入任意内容
在进行使用../
跨目录写入文件的时候,不会保留/
关键字
绕过的方式有三种,一个是使用反斜杠\
,但是在Linux
下可能会写入失败;第二种是将路径通过"
、或者'
包裹起来,这样就不会进入过滤点;第三种是将路径进行两次URL编码,在如上的分析中,可以发现,最后String类型的参数进行了URL解码。
漏洞复现
写入webshell
1 | POST /lfw/core/rpc HTTP/1.1 |
访问 http://172.20.10.19:8010/hello.jsp
rebeyond